﻿//using System;
//using System.Linq;
//using System.Collections.Generic;
//using FluentNHibernate;
//using FluentNHibernate.Mapping;
//using FluentNHibernate.Automapping;
//using FluentNHibernate.Automapping.Steps;
//using FluentNHibernate.MappingModel;
//using FluentNHibernate.MappingModel.ClassBased;
//using FluentNHibernate.MappingModel.Collections;

//namespace Caramel.FluentNHibernate.AutoMapping.Steps
//{
//    public class DictionaryStep : IAutomappingStep
//    {
//        private readonly IAutomappingConfiguration _cfg;
//        private readonly AutoKeyMapper _keys;

//        public DictionaryStep(IAutomappingConfiguration cfg)
//        {
//            _cfg = cfg;
//            _keys = new AutoKeyMapper(cfg);
//        }

//        public bool Closes(Type type, Type openGenericType)
//        {
//            return type.IsGenericType && type.GetGenericTypeDefinition() == openGenericType;
//        }

//        private bool ClosesInterface(Type type, Type openGenericInterface)
//        {
//            return type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == openGenericInterface);
//        }

//        public bool ShouldMap(Member member)
//        {
//            return
//                this.ClosesInterface(member.PropertyType, typeof(IDictionary<,>)) || 
//                this.Closes(member.PropertyType, typeof(IDictionary<,>));
//        }

//        public void Map(ClassMappingBase classMap, Member member)
//        {
//            if (member.DeclaringType != classMap.Type)
//            {
//                return;
//            }

//            var mapping = CollectionMapping.For(Collection.Map);

//            mapping.ContainingEntityType = classMap.Type;
//            mapping.Member = member;
//            mapping.SetDefaultValue(x => x.Name, member.Name);
//            mapping.SetDefaultValue(x => x.TableName, String.Format("`{0}`", member.DeclaringType.Name + member.Name));
//            _keys.SetKey(member, classMap, mapping);

//            this.SetDefaultAccess(member, mapping);
//            this.SetIndex(member, classMap, mapping);
//            this.SetElement(member, classMap, mapping);

//            classMap.AddCollection(mapping);
//        }

//        private void SetDefaultAccess(Member member, CollectionMapping mapping)
//        {
//            var resolvedAccess = MemberAccessResolver.Resolve(member);

//            if ((resolvedAccess != Access.Property) && (resolvedAccess != Access.Unset))
//            {
//                // if it's a property or unset then we'll just let NH deal with it, otherwise
//                // set the access to be whatever we determined it might be
//                mapping.SetDefaultValue(x => x.Access, resolvedAccess.ToString());
//            }

//            if (member.IsProperty && !member.CanWrite)
//            {
//                mapping.SetDefaultValue(x => x.Access, _cfg.GetAccessStrategyForReadOnlyProperty(member).ToString());
//            }
//        }

//        private void SetIndex(Member property, ClassMappingBase classMap, CollectionMapping mapping)
//        {
//            var index =
//                new IndexMapping()
//                {
//                    ContainingEntityType = classMap.Type,
//                    Type = new TypeReference(property.PropertyType.GetGenericArguments()[0])
//                };

//            index.AddDefaultColumn(new ColumnMapping { Name = "Name" });
//            mapping.SetDefaultValue(x => x.Index, index);
//        }

//        private void SetElement(Member property, ClassMappingBase classMap, CollectionMapping mapping)
//        {
//            var element = 
//                new ElementMapping
//                {
//                    ContainingEntityType = classMap.Type,
//                    Type = new TypeReference(property.PropertyType.GetGenericArguments()[1])
//                };

//            element.AddDefaultColumn(new ColumnMapping { Name = "Value" });
//            mapping.SetDefaultValue(x => x.Element, element);
//        }
//    }
//}
